package com.zpdhy.system.shiro;

import com.zpdhy.system.model.SysPermission;
import com.zpdhy.system.service.SysPermissionService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * Created by kedong on 2016/12/31.
 */
@Component
public class DynamicUpdatePermission {
    private final SysPermissionService permissionService;
    private final ShiroFilterFactoryBean shiroFilterFactoryBean;
    private final ShiroRealm shiroRealm;
    private final EhCacheManager ehCacheManager;

    @Autowired
    public DynamicUpdatePermission(SysPermissionService permissionService, ShiroFilterFactoryBean shiroFilterFactoryBean, ShiroRealm shiroRealm, EhCacheManager ehCacheManager) {
        this.permissionService = permissionService;
        this.shiroFilterFactoryBean = shiroFilterFactoryBean;
        this.shiroRealm = shiroRealm;
        this.ehCacheManager = ehCacheManager;
    }

    /**
     * 更新系统URL过滤器
     * 例如在后台新增加了模块，需要对新增的模块赋权限
     */
    public void updateShiroFilter() {
        synchronized (shiroFilterFactoryBean) {
            AbstractShiroFilter shiroFilter = null;
            try {
                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 获取过滤管理器
            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
                    .getFilterChainResolver();
            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

            // 清空初始权限配置
            manager.getFilterChains().clear();
            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();

            /**
             * 重新构建生成
             * 从数据库读取动态配置的
             */
            List<SysPermission> permissions = (List<SysPermission>) permissionService.findAll();
            // 拦截器
            Map<String, String> chains = ShiroConfiguration.getMap(permissions);

            for (Map.Entry<String, String> entry : chains.entrySet()) {
                String url = entry.getKey();
                String chainDefinition = entry.getValue().trim().replace(" ", "");
                manager.createChain(url, chainDefinition);
            }

            System.out.println("update shiro permission success...");


        }
    }

    /**
     * 重新赋值用户权限(在比如:给一个角色临时添加一个权限,需要调用此方法刷新权限,否则还是没有刚赋值的权限)
     *
     * @param username 用户名
     */
    public void updateUserPermission(String username) {
        Subject subject = SecurityUtils.getSubject();
        String realmName = subject.getPrincipals().getRealmNames().iterator().next();
        //第一个参数为用户名,第二个参数为realmName,test想要操作权限的用户
        SimplePrincipalCollection principals = new SimplePrincipalCollection(username, realmName);
        subject.runAs(principals);
        shiroRealm.getAuthorizationCache().remove(subject.getPrincipals());
        subject.releaseRunAs();
    }


    /**
     * 清空所有关联认证
     */
    public void clearAllCachedAuthorizationInfo2() {
        Cache<Object, AuthorizationInfo> cache = (Cache<Object, AuthorizationInfo>) ehCacheManager.getCacheManager();
        if (cache != null) {
            for (Object key : cache.keys()) {
                System.out.println(key + ":" + key.toString());
                cache.remove(key);
            }
        }
    }
}
